/****************************************************************
 * I am the AC 130 vs Pirate game. I allow the user to control an 
 * AC130 gunship in the hunt for Modern day pirates. The player  
 * will be allowed to roam free across a section of ocean/coastline.  
 * In the water there will be four types of vessels: Merchant  
 * ships that the player must protect, Pirate ships that the player  
 * must identify and destroy, Fishing boats that look like Pirate  
 * ships that the player must not destroy, and Friendly Navy ships  
 * that can capture pirates for extra points. Time permitting there  
 * may also be ground targets to attack. 
 *
 * Key elements of this project will be the Player/AC130, the Ships,  
 * the ShipAI system, the collision grid, the debris controller, the  
 * Ground/Water, Clouds, and scoring system. This project will make  
 * use of an external text file to store useful game parameters,  
 * thus allowing us to play balance the game without recompiling  
 * the executable. 
 *****************************************************************
 * I am the Ship object. I contain all the data to render a ship 
 * into the game sceene. I expect my container class to controll 
 * my destination point. I will update and draw the ship that
 * is stored by my internal classes.
 *****************************************************************/

#include <math.h>
#include "Ship.h"

/// I am the constructor. I set all the internal values
Ship::Ship(){
	shipType = 0;
	reDrawTmp = true;
	center = new Point;
	helper = new Point;
		// speed and turn rate values
	speedMax = 5;
	speedDlt = 0.5;
	speedCur = 0;

		// external navigation information
	atDest = false;	
	navIndex = -1;	
	navDest = new Point;	// set externaly
	nearDest = new Point;	// set externaly
	nearDesire = 0;	// priority of the near point
		// AI values
	// 0-player, 1-merchant, 2-fisherman, 3-pirate
	aiLoyalty = 3;
	// 0-navigate, 1-run, 2-attack, 3-go home, 4-hijacked, 5 derilict
	aiMode = 0;	

	tempBmp = create_bitmap(8,8);	// local
	btmBmp = tempBmp;	// external
	topBmp = create_bitmap(8,8);	// local

	// todo Crew stations

	hp = 100;	// hit pionts
		// sinking values
	maxSinkTime = 20;
	maxSinkPhase = 5;
	sinkTime = 0;
	sinkPhase = 0;
}

/// I am the dsestructor. I clean out all the internal values
Ship::~Ship(){
	delete(center);
	delete(helper);
	delete(navDest);
	delete(nearDest);
	destroy_bitmap(tempBmp);
	destroy_bitmap(topBmp);
}

/// I am the Initilizer function. I accept the game data
/// class and load internal data from it.
void Ship::Init(GameData * exGd){
	gd = exGd;
	maxSinkTime = gd->GetNum("shpSinkTime");
	maxSinkPhase = gd->GetNum("shpSinkTime");
		// ensure values are non 0
	if(maxSinkTime == 0)maxSinkTime = 20;
	if(maxSinkTime == 0)maxSinkTime = 10;

}

/// I am the bullet impact function. I compute where on the boat
/// a shot has struck and rener dammage
bool Ship::GetHit(Bullet * shot){
		// todo exit early if bullet loyalty is friendly

		// set helper relative to center
	helper->x = shot->center->x - center->x;
	helper->y = shot->center->y - center->y;

		// rotate helper to align with ship
	helper->RotateBy( angle);
	if(fabs(helper->x) > btmBmp->w/2 || fabs(helper->y)> btmBmp->h/2)
		return false;	//no inside bitmap
		// find color at point
	int pxlCol =getpixel(btmBmp, helper->x+btmBmp->w/2, helper->y+btmBmp->h/2);
		// return false if on magenta layer
	if(getr(pxlCol)==255 && getg(pxlCol) == 0 && getb(pxlCol)==255)
		return false;
		// decriment hitpoints
	hp -= shot->dammage;

	// paint the shot's blast mask
	int stX = helper->x + btmBmp->w/2 - shot->blastMask->w/2;
	int stY = helper->y + btmBmp->h/2 - shot->blastMask->h/2;
	for(int yitor = 0; yitor < shot->blastMask->h; yitor++){
		for(int xitor = 0; xitor < shot->blastMask->w; xitor++){
				// invoke painting function
			PaintHit(topBmp, shot->blastMask, 
				stX+xitor, stY+yitor, xitor, yitor);
		}
	}
		// set flag toredraw btmTemp
	reDrawTmp = true;
		// todo check crew
}

/// I am the mask paint function. I color the tgt according
/// to what value is on the mask.
void Ship::PaintHit(BITMAP * tgt, BITMAP *mask, 
					int tgtX, int tgtY, int maskX, int maskY)
{
		// don't draw if tgt X & Y are oustide tgt
	if( tgtX < 0 || tgtX > tgt->w-1 || tgtY < 0 || tgtY > tgt->h)
		return;
	int mskCol = getpixel(mask, maskX, maskY);
		// don't draw if mask is black
	if(getr(mskCol)==0 && getg(mskCol) == 0 && getb(mskCol)==0)
		return ;
		// get pixel color
	int tgtCol = getpixel(tgt, tgtX, tgtY);
		// don't draw if tgt is magenta
	if(getr(tgtCol)==255 && getg(tgtCol) == 0 && getb(tgtCol)==255)
		return ;
		// put the mask color onto the tgtBitmap
	putpixel(tgt, tgtX, tgtY, mskCol);
	return;
}

/// I am the update function. I updatet he ship's internal values
/// such that it moves toward its desired location. I set the tmpBitmap
/// to what ever the current ships state is.
void Ship::Update(){
		// not active
	if(sinkPhase >= maxSinkPhase) return;
	if(hp <= 0){
		sinkTime += 1;
		if(sinkTime >= maxSinkTime){
			sinkTime = 0;
			sinkPhase += 1;
			reDrawTmp = true;
		}
			// exicute redraw on temp	
	}
	if(reDrawTmp == true){
		DrawTemp();
		reDrawTmp = false;
	}


}


/// Set the ai based navigation point
void Ship::SetNavi(){

}


/// I am the draw funciton. I render the ship into the game forld if it is
/// visable
void Ship::Draw(Camera * cam){
	//if(sinkPhase == maxSinkPhase) return;
	//if( cam->IsInScreen(center, tempBmp->w+tempBmp->h) == false) return;
	cam->WorldPivotCtr(tempBmp, center, angle);
	//cam->WorldPivotCtr(btmBmp, center, angle);
	//cam->WorldPivotCtr(topBmp, center, angle);
		// draw crew
}

/// I repopulate the tmpBmp with the ships current visual state
void Ship::DrawTemp(){
	clear_to_color(tempBmp, makecol(255,0,255));
	draw_sprite(tempBmp, btmBmp, 0,0);
	draw_sprite(tempBmp, topBmp, 0,0);
	if(sinkPhase == 0)return;	// done don't do sink overlay
		// do sink overlay
	int waterR = gd->GetNum("waterRed");
	int waterG = gd->GetNum("waterGreen");
	int waterB = gd->GetNum("waterBlue");
	for(int yitor = 0; yitor < tempBmp->h; yitor++){
		for(int xitor = 0; xitor < tempBmp->w; xitor++){
			int pixcol = getpixel(tempBmp, xitor, yitor);
				// weight average
			if(getr(pixcol)==255 && getg(pixcol) == 0 && getb(pixcol)==255){
			}else{
				int rval = (getr(pixcol)*(maxSinkPhase - sinkPhase)/maxSinkPhase)+
					(waterR*sinkPhase/maxSinkPhase);
				int gval = (getg(pixcol)*(maxSinkPhase - sinkPhase)/maxSinkPhase)+
					(waterG*sinkPhase/maxSinkPhase);
				int bval = (getb(pixcol)*(maxSinkPhase - sinkPhase)/maxSinkPhase)+
					(waterB*sinkPhase/maxSinkPhase);
				putpixel(tempBmp, xitor, yitor, makecol(rval,gval,bval));
			}
		}
	}

}